package cn.lili.controller.feign.order;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.distribution.client.DistributionClient;
import cn.lili.modules.distribution.entity.dos.Distribution;
import cn.lili.modules.distribution.entity.vos.DistributionOrderSearchParams;
import cn.lili.modules.member.client.CityDistributionClient;
import cn.lili.modules.member.client.UnionClient;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.CityDistribution;
import cn.lili.modules.member.entity.dos.CityDistributionCancel;
import cn.lili.modules.member.entity.dos.Union;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.member.entity.dto.CityDistributionDTO;
import cn.lili.modules.member.entity.enums.ComissStatusEnum;
import cn.lili.modules.operationcenter.client.OperationCenterClient;
import cn.lili.modules.operationcenter.entity.dos.OperationCenter;
import cn.lili.modules.order.cart.render.TradeBuilder;
import cn.lili.modules.order.order.client.OrderClient;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderFlow;
import cn.lili.modules.order.order.entity.dos.OrderFlowProfitSharingError;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.*;
import cn.lili.modules.order.order.entity.dto.OrderExportDTO;
import cn.lili.modules.order.order.entity.dto.OrderFlowQueryDTO;
import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
import cn.lili.modules.order.order.entity.dto.UserMoneyDTO;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.entity.enums.ProfitSharingStatusEnum;
import cn.lili.modules.order.order.entity.vo.*;
import cn.lili.modules.order.order.mapper.OrderFlowMapper;
import cn.lili.modules.order.order.service.OrderFlowProfitSharingErrorService;
import cn.lili.modules.order.order.service.OrderFlowService;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.order.task.OrderEveryDayTask;
import cn.lili.modules.payment.client.PaymentClient;
import cn.lili.modules.payment.entity.dto.UserPointUpdateDTO;
import cn.lili.modules.payment.entity.enums.UserPointServiceEnum;
import cn.lili.modules.promotion.client.GreenClient;
import cn.lili.modules.promotion.entity.dos.GreenContributionInfo;
import cn.lili.modules.promotion.entity.dto.GreenConfigValueDTO;
import cn.lili.modules.promotion.entity.enums.GreenAmountInfoStatusEnum;
import cn.lili.modules.promotion.entity.enums.GreenAmountInfoTypeEnum;
import cn.lili.modules.system.client.IRegionClient;
import cn.lili.modules.system.client.SettingClient;
import cn.lili.modules.system.entity.dos.Region;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.DistributionSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.entity.vo.Traces;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单 feign client
 *
 * @author Chopper
 * @version v1.0 2021-12-07 18:34
 */
@RestController
@RequiredArgsConstructor
@Slf4j
public class OrderFeignController implements OrderClient {

    private final OrderService orderService;
    private final OrderItemService orderItemService;

    private final TradeBuilder tradeBuilder;

    private final OrderEveryDayTask orderEveryDayTask;

    private final OrderFlowService orderFlowService;

    private final CityDistributionClient cityDistributionClient;

    private final OrderFlowMapper orderFlowMapper;

    private final UserClient userClient;

    private final DistributionClient distributionClient;

    private final IRegionClient regionClient;
    private final PaymentClient paymentClient;
    private final GreenClient greenClient;

    private final UnionClient unionClient;
    private final SettingClient settingClient;
    private final OrderFlowProfitSharingErrorService profitSharingErrorService;
    private final OperationCenterClient operationCenterClient;

    @Override
    public Order getBySn(String sn) {
        return orderService.getBySn(sn);
    }

    /**
     * 系统取消订单
     *
     * @param orderSn 订单编号
     * @param reason  错误原因
     */
    @Override
    public void systemCancel(String orderSn, String reason) {
        orderService.systemCancel(orderSn, reason);
    }

    @Override
    public Double getPaymentTotal(String orderSn) {
        return tradeBuilder.getPaymentTotal(orderSn);
    }

    @Override
    public OrderDetailVO queryDetail(String sn) {
        return orderService.queryDetail(sn);
    }

    @Override
    public List<Order> getByTradeSn(String sn) {
        return orderService.getByTradeSn(sn);
    }

    @Override
    public List<Order> getByParentSn(String sn) {
        return orderService.getByParentSn(sn);
    }

    /**
     * 订单信息
     *
     * @param orderSearchParams 查询参数
     * @return 订单信息
     */
    @Override
    public List<Order> queryListByParams(OrderSearchParams orderSearchParams) {
        return orderService.queryListByParams(orderSearchParams);
    }

    /**
     * 根据促销查询订单
     *
     * @param orderPromotionType 订单类型
     * @param payStatus          支付状态
     * @param parentOrderSn      依赖订单编号
     * @param orderSn            订单编号
     * @return 订单信息
     */
    @Override
    public List<Order> queryListByPromotion(
            String orderPromotionType, String payStatus, String parentOrderSn, String orderSn) {
        return orderService.queryListByPromotion(orderPromotionType, payStatus, parentOrderSn, orderSn);
    }

    @Override
    public List<Order> queryListByPromotionId(String orderPromotionType, String payStatus, String parentOrderSn, String promotionId, String skuId) {
        return orderService.queryListByPromotionId(orderPromotionType, payStatus, parentOrderSn, promotionId, skuId);
    }

    /**
     * 根据促销查询订单
     *
     * @param orderPromotionType 订单类型
     * @param payStatus          支付状态
     * @param parentOrderSn      依赖订单编号
     * @param orderSn            订单编号
     * @return 订单信息
     */
    @Override
    public long queryCountByPromotion(
            String orderPromotionType, String payStatus, String parentOrderSn, String orderSn) {
        return orderService.queryCountByPromotion(orderPromotionType, payStatus, parentOrderSn, orderSn);
    }

    /**
     * 检查是否开始虚拟成团
     *
     * @param pintuanId   拼团活动id
     * @param requiredNum 成团人数
     * @param fictitious  是否开启成团
     * @return 是否成功
     */
    @Override
    public boolean checkFictitiousOrder(String pintuanId, Integer requiredNum, Boolean fictitious) {
        return orderService.checkFictitiousOrder(pintuanId, requiredNum, fictitious);
    }

    @Override
    public void save(Order order) {
        orderService.save(order);
    }

    @Override
    public void afterOrderConfirm(String orderSn) {
        orderService.afterOrderConfirm(orderSn);
    }


    /**
     * 自动成团订单处理
     *
     * @param pintuanId     拼团活动id
     * @param parentOrderSn 拼团订单sn
     */
    @Override
    public void agglomeratePintuanOrder(String pintuanId, String parentOrderSn) {
        orderService.agglomeratePintuanOrder(pintuanId, parentOrderSn);
    }

    @Override
    public void update(Order order) {
        LambdaUpdateWrapper<Order> lambdaUpdateWrapper = new LambdaUpdateWrapper<Order>()
                .set(Order::getVerificationCode, order.getVerificationCode())
                .eq(Order::getSn, order.getSn());
        if (StringUtils.isNotEmpty(order.getMhId())) {
            lambdaUpdateWrapper.set(Order::getMhId, order.getMhId());
        }
        if (StringUtils.isNotEmpty(order.getMhName())) {
            lambdaUpdateWrapper.set(Order::getMhName, order.getMhName());
        }
        if (StringUtils.isNotEmpty(order.getMhName())) {
            lambdaUpdateWrapper.set(Order::getMhName, order.getMhName());
        }
        if (StringUtils.isNotEmpty(order.getFreeErrorMessage()) && order.getFreeErrorMessage().equals(StringPool.NULL)) {
            lambdaUpdateWrapper.set(Order::getFreeErrorMessage, null);
        }
        if (StringUtils.isNotEmpty(order.getCustomsErrorMessage()) && order.getCustomsErrorMessage().equals(StringPool.NULL)) {
            lambdaUpdateWrapper.set(Order::getCustomsErrorMessage, null);
        }
        orderService.update(lambdaUpdateWrapper);
    }

    @Override
    public Order getOne(Order order) {

        LambdaQueryWrapper<Order> lambdaQueryWrapper =
                new LambdaQueryWrapper<Order>()
                        .eq(Order::getVerificationCode, order.getVerificationCode())
                        .eq(Order::getStoreId, order.getStoreId());

        return orderService.getOne(lambdaQueryWrapper);
    }

    /**
     * 查询订单列表分页
     *
     * @param orderSearchParams
     * @return
     */
    @Override
    public Page<OrderSimpleVO> queryByParams(OrderSearchParams orderSearchParams) {
        return orderService.queryByParams(orderSearchParams);
    }

    @Override
    public Page<OrderSimpleVO> distributionQuery(DistributionOrderSearchParams distributionOrderSearchParams){
        return orderService.distributionQuery(distributionOrderSearchParams);
    }

    /**
     * 订单发货
     *
     * @param orderSn
     * @param logisticsNo
     * @param logisticsId
     * @return
     */
    @Override
    public Order delivery(String orderSn, String logisticsNo, String logisticsId) {
        return orderService.delivery(orderSn, logisticsNo, logisticsId);
    }

    /**
     * 取消订单
     *
     * @param orderSn
     * @param reason
     * @return
     */
    @Override
    public Order cancel(String orderSn, String reason) {
        return orderService.cancel(orderSn, reason,"",null);
    }

    /**
     * 下载待发货的订单列表
     *
     * @param response
     * @param logisticsName
     */
    @Override
    public void getBatchDeliverList(HttpServletResponse response, List<String> logisticsName) {
        orderService.getBatchDeliverList(response, logisticsName);
    }

    /**
     * 上传文件进行订单批量发货
     *
     * @param files
     */
    @Override
    public void batchDeliver(MultipartFile files) {
        orderService.batchDeliver(files);
    }

    /**
     * 查询订单导出列表
     *
     * @param orderSearchParams
     * @return
     */
    @Override
    public List<OrderExportDTO> queryExportOrder(OrderSearchParams orderSearchParams) {
        return orderService.queryExportOrder(orderSearchParams);
    }

    /**
     * 获取物流踪迹
     *
     * @param orderSn
     * @return
     */
    @Override
    public Traces getTraces(String orderSn) {
        return orderService.getTraces(orderSn);
    }

    /**
     * 供应商订单统计
     *
     * @param supplierId
     * @return
     */
    @Override
    public Map<String, Long> pendingPaymentOrderNum(String supplierId) {
        return orderService.pendingPaymentOrderNum(supplierId);
    }

    @Override
    public void everyDayTask() {
        orderEveryDayTask.execute();

        //系统取消异常订单（海关与保税仓的商品）  ..  不放在execute里面是因为有个小时级别的定时任务也在引用此方式（每小时进行一次重试，一天还没重试成功就自动取消）
        try {
            LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
            orderLambdaQueryWrapper.and(q -> q.isNotNull(Order::getCustomsErrorMessage).or().isNotNull(Order::getFreeErrorMessage));
            orderLambdaQueryWrapper.ne(Order::getOrderStatus, OrderStatusEnum.CANCELLED.name());
            List<Order> orderList = orderService.list(orderLambdaQueryWrapper);
            if (CollectionUtil.isEmpty(orderList)) {
                return;
            }
            for (Order order : orderList) {
                log.info("海关或保税仓上传异常，系统取消 == {}", JSONObject.toJSONString(order));
                orderService.cancel(order.getSn(), "海关或保税仓上传异常，系统取消", order.getBuyerId());
            }
        } catch (Exception e) {
            log.error("异常订单取消异常", e);
        }

        try {
            //查询供应链订单状态,并同步
            orderService.syncSupplyChain();
        } catch (Exception e) {
            log.error("供应链查询,同步状态异常", e);
        }
    }

    @Override
    public List<OrderFlow> orderFlowList(String orderSn) {
        return orderFlowService.listByOrderSn(orderSn);
    }

    @Override
    public Map<String, Object> getSumPrice() {
        return orderService.sumPrice();
    }

    @Override
    public Long getCountByBuyerId(String buyerId) {
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getBuyerId, buyerId);
        orderLambdaQueryWrapper.isNotNull(Order::getMhId);
        return orderService.count(orderLambdaQueryWrapper);
    }

    @Override
    public Double getMoneyByUid(String uid) {
        LambdaQueryWrapper<OrderFlow> orderFlowLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderFlowLambdaQueryWrapper.eq(OrderFlow::getMemberId, uid);
        orderFlowLambdaQueryWrapper.eq(OrderFlow::getProfitSharing, ProfitSharingStatusEnum.FINISHED.name());
        orderFlowLambdaQueryWrapper.select(OrderFlow::getId, OrderFlow::getFlowPrice);
        List<OrderFlow> orderFlows = orderFlowService.list(orderFlowLambdaQueryWrapper);
        if (CollectionUtil.isEmpty(orderFlows)) {
            return 0D;
        }
        return orderFlows.stream().filter(f -> f.getFlowPrice() != null).map(OrderFlow::getFlowPrice).mapToDouble(Double::valueOf).sum();
    }

    @Override
    public Double getShopkeeperMoneyByUid(String uid) {
        LambdaQueryWrapper<OrderFlow> orderFlowLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderFlowLambdaQueryWrapper.eq(OrderFlow::getMemberId, uid);
        orderFlowLambdaQueryWrapper.eq(OrderFlow::getIsPay, Boolean.TRUE);
        orderFlowLambdaQueryWrapper.select(OrderFlow::getId, OrderFlow::getFlowPrice);
        List<OrderFlow> orderFlows = orderFlowService.list(orderFlowLambdaQueryWrapper);
        if (CollectionUtil.isEmpty(orderFlows)) {
            return 0D;
        }
        return orderFlows.stream().filter(f -> f.getFlowPrice() != null).map(OrderFlow::getFlowPrice).mapToDouble(Double::valueOf).sum();
    }

    /**
     * 查询店主列表直推业绩
     * @param paramMap 店主id, 下级id集合
     * @return  店主id,下级业绩总数(直推业绩)
     */
    @Override
    public Map<String, OrderFlow> selectSubUserFlowPrice(Map<String, List<String>> paramMap) {
        Map<String, OrderFlow> resultMap = new HashMap<>();
        // TODO: 2024/1/7 这里可能涉及使用大量内存，后期优化可考虑分段 list查询
        List<String> paramSubIds = new ArrayList<>();
        //获取paramMap里的所有List<String>
        Iterator<List<String>> iterator = paramMap.values().iterator();
        while (iterator.hasNext()) {
            paramSubIds.addAll(iterator.next());
        }
        //根据members获取所有订单
        SubUserFlowPriceVO subUserFlowPrice = new SubUserFlowPriceVO();
        subUserFlowPrice.setParamSubIds(String.join(",", paramSubIds));
        List<OrderFlow> orderFlows = orderFlowService.selectSubUserFlowPrice(subUserFlowPrice);
        if (CollUtil.isNotEmpty(orderFlows)) {
            Map<String, OrderFlow> orderFlowMap = orderFlows.stream()
                    .collect(Collectors.toMap(OrderFlow::getMemberId, flow -> flow));
            //遍历paramMap店主
            paramMap.entrySet().stream()
                    .forEach(entry -> {
                        String parentId = entry.getKey();
                        //店主对应的下级
                        List<String> values = entry.getValue();
                        values.stream().forEach(v -> {
                            //店主结果集map取值
                            OrderFlow parentOrderFlow = resultMap.get(parentId);
                            //业绩
                            double subPrice = orderFlowMap.get(v) != null ? orderFlowMap.get(v).getFlowPrice() : 0.0;
                            double totalCommiss = orderFlowMap.get(v) != null ? orderFlowMap.get(v).getTotalCommiss() : 0.0;
                            if (null == parentOrderFlow) {
                                //赋值
                                parentOrderFlow = new OrderFlow();
                                parentOrderFlow.setFlowPrice(subPrice);
                                parentOrderFlow.setTotalCommiss(totalCommiss);
                                resultMap.put(parentId, parentOrderFlow);
                            } else {
                                //累加业绩
                                parentOrderFlow.setFlowPrice(parentOrderFlow.getFlowPrice() + subPrice);
                                parentOrderFlow.setTotalCommiss(parentOrderFlow.getTotalCommiss() + totalCommiss);
                                resultMap.put(parentId, parentOrderFlow);
                            }
                        });
                    });
        }
        return resultMap;
    }

    /**
     * 计算团队每位成员本月的金额
     *
     * @param userIdList 用户ID
     * @return 每位成员本月的金额
     */
    @Override
    public List<OrderFlow> computeMoney(List<String> userIdList) {
        SubUserFlowPriceVO subUserFlowPrice = new SubUserFlowPriceVO();
        // 获取本月第一天的开始时间
        LocalDate firstDayOfMonth = LocalDate.now().withDayOfMonth(1);
        Date beginDate = Date.from( LocalDateTime.of(firstDayOfMonth, LocalTime.MIN).atZone(ZoneId.systemDefault()).toInstant());
        // 获取本月最后一天的结束时间
        LocalDate lastDayOfMonth = LocalDate.now().withDayOfMonth(firstDayOfMonth.lengthOfMonth());
        Date endDate = Date.from(LocalDateTime.of(lastDayOfMonth, LocalTime.MAX).atZone(ZoneId.systemDefault()).toInstant());

        subUserFlowPrice.setParamSubIds(String.join(",", userIdList));
        subUserFlowPrice.setBeginDate(beginDate);
        subUserFlowPrice.setEndDate(endDate);
        List<OrderFlow> orderFlows = orderFlowService.selectSubUserFlowPrice(subUserFlowPrice);
        return orderFlows;
    }


    /**
     * 查询订单数
     * @param userIdList
     * @return
     */
    @Override
    public Map<String, Integer> selectCountOrderByUserIds(List<String> userIdList, String parentId) {
        return orderFlowService.selectCountOrderByUserIds(userIdList, parentId);
    }

    @Override
    public Map<String, Double> selectCurrentConsumptionByUserIds(List<String> userIdList, String parentId) {
        return orderFlowService.selectCurrentConsumptionByUserIds(userIdList, parentId);
    }

    @Override
    public Map<String, Double> selectCumulativeConsumptionByUserIds(List<String> userIdList, String parentId) {
        return orderFlowService.selectCumulativeConsumptionByUserIds(userIdList, parentId);
    }

    /**
     * 工会经费查询
     * @param areaId
     * @return
     */
    @Override
    public Double getMonthUnionGreenScoreByAreaId(String areaId) {
        return orderFlowService.getMonthUnionGreenScoreByAreaId(areaId);
    }

    @Override
    public OrderVO todayOrderForUnion(String province, String city) {
        return orderService.todayOrderForUnion(province,city);
    }

    public OrderVO todayOrderForUnionV2(List<String> buyerIdList){
        return orderService.todayOrderForUnion(buyerIdList);
    }

    @Override
    public Page<OrderVO> getOrderForUnionByPageV2(List<String> buyerIdList, Integer pageNo, Integer pageSize) {
        return orderService.getOrderByPage(buyerIdList,pageNo,pageSize);
    }

//    @Override
//    public Page<OrderVO> topOrdersForUnion(String province, String city, Integer pageNo, Integer pageSize) {
//        return orderService.getOrderByPage(province,city,pageNo,pageSize);
//    }

    @Override
    public Page<OrderFlowDTO> getCurrentMonthByUnionMember(UnionOrderParams params) {
        return orderFlowService.getCurrentMonthByUnionMember(params);
    }

    @Override
    public PerformanceDetailVO getCurrentMonthStatisticsByMember(UnionOrderParams params) {
        return orderFlowService.getCurrentMonthStatisticsByMember(params);
    }

    @Override
    public Page<OrderFlowDTO> getLastMonthByUnionMember(UnionOrderParams params) {
        return orderFlowService.getLastMonthByUnionMember(params);
    }

    @Override
    public PerformanceDetailVO getLastMonthStatisticsByMember(UnionOrderParams params) {
        return orderFlowService.getLastMonthStatisticsByMember(params);
    }

    @Override
    public Page<OrderFlow> getUnionMoneyDetail(UnionOrderParams params) {
        return orderFlowService.getUnionMoneyDetail(params);
    }

    @Override
    public PerformanceDetailVO getUnionMoneyStatisticsDetail(UnionOrderParams params) {
        return orderFlowService.getUnionMoneyStatisticsDetail(params);
    }

    @Override
    public PerformanceDetailVO getCurrentMonthUnionOrderCountByUnion(String areaId) {
        return orderFlowService.getCurrentMonthUnionOrderCountByUnion(areaId);
    }

    @Override
    public PerformanceDetailVO getLastMonthUnionOrderByUnion(String areaId) {
        return orderFlowService.getLastMonthUnionOrderByUnion(areaId);
    }

    @Override
    public void executeCityDistributionLastMonthOrder() {
        /**
         * 按本城（区/县）直推订单业绩进行排序，本月直推业绩TOP1的店主即可任职城主，若业绩并列第一则以直推店主数量高的店主视为城主。
         */
        // 定时任务:店主升级城主

        //获取上个月时间
        YearMonth lastMonth = YearMonth.now().minusMonths(1);
        LocalDateTime begin = lastMonth.atDay(1).atStartOfDay();
        LocalDateTime end = lastMonth.atEndOfMonth().atTime(23, 59, 59);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取升级城主所需推广的下级店主人数配置
        Integer subDistributionCount = 20;
        Setting setting = settingClient.get(SettingEnum.DISTRIBUTION_SETTING.name());
        DistributionSetting distributionSetting = JSONUtil.toBean(setting.getSettingValue(), DistributionSetting.class);
        if (distributionSetting != null && StringUtils.isNotEmpty(distributionSetting.getCastellan())) {
            subDistributionCount =(Integer.valueOf(distributionSetting.getCastellan()));
        }
        //获取上个月订单有哪些区域
        log.info("#executeCityDistributionLastMonthOrder# 升级城主定时任务, 查询订单区域: regionList,参数:开始时间:{},结束时间:{}", formatter.format(begin), formatter.format(end));
        List<String> regionList = orderService.executeCityDistributionLastMonthOrder(begin, end, subDistributionCount);
        if (CollectionUtil.isEmpty(regionList)) {
            log.info("#executeCityDistributionLastMonthOrder# 升级城主定时任务, 查询订单区域: regionList结果为空,参数:开始时间:{},结束时间:{}", formatter.format(begin), formatter.format(end));
            return;
        }
        for (String regionId : regionList) {
            //获取top1
            log.info("#executeCityDistributionLastMonthOrder# 升级城主定时任务, 查询订单区域: userMoneyList ,参数:regionId:{},开始时间:{},结束时间:{}",regionId, formatter.format(begin), formatter.format(end));
            List<UserMoneyDTO> userMoneyList = orderFlowMapper.getUserMoneyList(null, regionId, formatter.format(begin), formatter.format(end), 20);
            if (CollectionUtil.isEmpty(userMoneyList)) {
                log.info("#executeCityDistributionLastMonthOrder# 升级城主定时任务, 查询订单区域: userMoneyList 结果为空,参数:regionId:{},开始时间:{},结束时间:{}",regionId, formatter.format(begin), formatter.format(end));
                continue;
            }
            //获取本月这个区域的取消资格记录
            List<CityDistributionCancel> cityDistributionCancelList = cityDistributionClient.getCityDistributionCancelByRegion(regionId);
            //创建城主
            UserMoneyDTO userMoneyDTO = userMoneyList.get(0);
            if (CollectionUtil.isNotEmpty(cityDistributionCancelList)) {
                userMoneyDTO = this.getUserMoneyDTO(cityDistributionCancelList, userMoneyList);
                if (userMoneyDTO == null) {
                    continue;
                }
            }
            log.info("#executeCityDistributionLastMonthOrder# 城主已查出, 准备保存城主对象信息:{}", JSONObject.toJSONString(userMoneyDTO));
            CityDistribution cityDistribution = this.createCityDistribution(userMoneyDTO, regionId);
            cityDistributionClient.createCityDistribution(cityDistribution);
        }
    }

    /**
     * 如果是去取消过资格的就延续下一个
     *
     * @param cityDistributionCancelList 取消资格列表
     * @param userMoneyList 用户列表
     * @return 单条用户，如果不存在取消资格的用户则返回null
     */
    private UserMoneyDTO getUserMoneyDTO(List<CityDistributionCancel> cityDistributionCancelList, List<UserMoneyDTO> userMoneyList) {
        // 遍历用户列表
        for (UserMoneyDTO userMoney : userMoneyList) {
            // 检查该用户是否存在于取消资格列表中
            boolean isCancelled = cityDistributionCancelList.stream()
                    .anyMatch(cancel -> cancel.getMemberId().equals(userMoney.getMemberId()));
            // 如果用户没有取消资格，则返回该用户
            if (!isCancelled) {
                return userMoney;
            }
        }
        // 如果所有用户都被取消资格，则返回null
        return null;
    }

    /**
     * 创建城主
     */
    public CityDistribution createCityDistribution(UserMoneyDTO userMoneyDTO, String regionId) {
        //获取当前区域是否已有城主，并且属于指定或更改的就不新增操作了。
        CityDistribution cityDistribution = cityDistributionClient.getCityDistributionByDistrictCodeAndMonthDate(regionId);
        OrderFlowQueryDTO queryDto = new OrderFlowQueryDTO();
        //当前区域没有城主
        if (cityDistribution == null || StringUtils.isEmpty(cityDistribution.getId())) {
            cityDistribution = new CityDistribution();
            cityDistribution.setComissStatus(1);
        }
        //已有城主且城主是,指定城主和,更换城主.
        if (cityDistribution.getRequired() != null && cityDistribution.getRequired()) {
            return cityDistribution;
        }
        String memberId = userMoneyDTO.getMemberId();
        User user = userClient.getById(memberId);
        if (user != null && StringUtils.isNotEmpty(user.getId())) {
            cityDistribution.setNickName(user.getNickName());
            cityDistribution.setMemberId(user.getId());
        }
        Distribution distribution = distributionClient.getDistribution(memberId);
        cityDistribution.setDistributionId(distribution != null && StringUtils.isNotEmpty(distribution.getId()) ? distribution.getId() : null);
        queryDto.setMemberId(memberId);
        LocalDate localDate = LocalDate.now();
        queryDto.setStartLocalDate(LocalDate.of(localDate.getYear(), localDate.getMonth().getValue(), 1));
        queryDto.setEndLocalDate(queryDto.getStartLocalDate().plusMonths(1));
        queryDto.setJoinAddressCode(regionId);
        Double total = orderFlowMapper.totalComiss(queryDto);
        cityDistribution.setTotalComiss(total != null ? total : 0D);
        cityDistribution.setYearDate(Year.now().getValue());
        cityDistribution.setMonthDate(YearMonth.now().getMonthValue());
        cityDistribution.setDayDate(YearMonth.now().lengthOfMonth());
        cityDistribution.setDistributionStatus(true);
        //当前有区域为空时直接返回
        Region districtRegion = regionClient.getRegionById(regionId);
        if (districtRegion == null || StringUtils.isEmpty(districtRegion.getId())) {
            log.info("#executeCityDistributionLastMonthOrder# --> #createCityDistribution# 升级城主定时任务, 当前有区域为空时直接返回: districtRegion 结果为空,参数为:{}", regionId);
            return cityDistribution;
        }
        cityDistribution.setDistrictCode(districtRegion.getId());
        cityDistribution.setDistrictName(districtRegion.getName());

        Region cityRegion = regionClient.getRegionById(districtRegion.getParentId());
        if (cityRegion == null || StringUtils.isEmpty(cityRegion.getId())) {
            log.info("#executeCityDistributionLastMonthOrder# --> #createCityDistribution# 升级城主定时任务, 当前有区域为空时直接返回: cityRegion 结果为空,参数为:{}", districtRegion.getParentId());
            return cityDistribution;
        }
        cityDistribution.setCityCode(cityRegion.getId());
        cityDistribution.setCityName(cityRegion.getName());

        Region privinceRegion = regionClient.getRegionById(cityRegion.getParentId());
        if (privinceRegion == null || StringUtils.isEmpty(privinceRegion.getId())) {
            log.info("#executeCityDistributionLastMonthOrder# --> #createCityDistribution# 升级城主定时任务, 当前有区域为空时直接返回: privinceRegion 结果为空,参数为:{}", cityRegion.getParentId());
            return cityDistribution;
        }
        cityDistribution.setPrivinceCode(privinceRegion.getId());
        cityDistribution.setPrivinceName(privinceRegion.getName());
        return cityDistribution;
    }




    /**
     * 城主佣金结算、发放
     */
    @Override
    public void executeCityDistributionComissLastMonthOrder() {
        /**定时任务:城主佣金结算发放
         次月，每日0点，查询该区域本月订单是否还有待结算。
         如全部结算完成，则发放奖励
         开启配置则发放贡献值
         未开启则发放绿色积分*/
         this.execute(LocalDate.now().minusMonths(1));
    }

    /**
     * 执行收益发放
     *
     */
    private boolean execute(LocalDate lastMonthDate) {
        //上月日期
//        LocalDate lastMonthDate = LocalDate.now().minusMonths(1);
        CityDistributionDTO dto = new CityDistributionDTO();
        dto.setDateParam(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(lastMonthDate));
        //查询上月城主,不分页
        dto.setPageNumber(0);
        dto.setPageSize(0);
        dto.setComissStatus(ComissStatusEnum.WAITTING.type);
        log.info("execute  dto == {}", JSONObject.toJSONString(dto));
        Page<CityDistribution> cityDisPage = cityDistributionClient.getCityDistribution(dto);
        if(CollUtil.isEmpty(cityDisPage.getRecords())){
            log.info("#executeCityDistributionComissLastMonthOrder# 查询上月城主不分页, cityDisPage为空,上月无城主,参数:{}", JSONObject.toJSONString(dto));
            return true;
        }
        //收益类型: 1,贡献值 2,飞语绿色积分
        Integer comissType = null;
        //查询最新功能配置
        GreenConfigValueDTO greenConfigValueDTO = greenClient.getNewGreenConfigValueDTO();
        if(greenConfigValueDTO.getPutinto().getCastellan()!=null && greenConfigValueDTO.getPutinto().getCastellan()){
            //收益类型为：贡献值
            comissType = 1;
        } else {
            //收益类型:飞语绿色积分
            comissType = 2;
        }
        //兑换为贡献值
        //查询订单时间条件
        //取上月的第一天为开始日期
        LocalDate startDate = lastMonthDate.withDayOfMonth(1);
        //取下个月的第一天为结束日期
        LocalDate endDate = startDate.plusMonths(1);
        for (CityDistribution city : cityDisPage.getRecords()) {
            int result = 0;
            String joinAddress = city.getPrivinceCode() + "," + city.getCityCode() + "," + city.getDistrictCode();
            if (StringUtils.isEmpty(city.getMemberId()) || !city.getDistributionStatus()) {
                log.info("#executeCityDistributionComissLastMonthOrder# 该区域没有城主,不进行发放奖励,城主id:{},区域id:{},跳过处理", city.getId(), joinAddress);
                continue;
            }
            //根据区域查询本月的订单
            if (orderService.isExistsUnCompletedOrder(joinAddress, startDate, endDate)) {
                log.info("#executeCityDistributionComissLastMonthOrder# 上个月还有未完成的订单,城主id:{},区域id:{},跳过处理", city.getId(), joinAddress);
                continue;
            }
            User cityUser = userClient.getById(city.getMemberId());
            if (cityUser == null) {
                log.info("#executeCityDistributionComissLastMonthOrder# 城主用户信息未找到,城主用户id:{},城主id:{},区域id:{},跳过处理", city.getMemberId(), city.getId(), joinAddress);
                continue;
            }
            //分页查询订单量,分批执行,1次执行5000条
            int pageNum = 1, pageSize = 5000;
            List<OrderItemViewVO> orderList = orderService.getCityDistributionSumComissByTaskTime(pageNum, pageSize, joinAddress, startDate, endDate);
            log.info("#executeCityDistributionComissLastMonthOrder# 分页查询订单量,分批执行,1次执行5000条,pageNum:{},pageSize:{},joinAddress:{},startDate:{},endDate:{}", pageNum, pageSize, joinAddress, startDate, endDate);
            while (CollUtil.isNotEmpty(orderList)) {
                List<String> ids = new ArrayList<>();
                for (OrderItemViewVO vo : orderList) {
                    GreenContributionInfo info = new GreenContributionInfo();
                    info.setOrderSn(vo.getOrderSn());
                    info.setUserId(city.getMemberId());
                    info.setUserType(SceneEnums.CASTELLAN.name());
                    info.setUsername(cityUser.getUsername());
                    info.setNickName(city.getNickName());
                    info.setFace(cityUser.getFace());
                    info.setScoreNumber(new BigDecimal(vo.getCastellanGreenScore()));
                    //AUTO_DIVIDEND("自动分红")
                    info.setType(GreenAmountInfoTypeEnum.AUTO_DIVIDEND.name());
                    //TO_BE_SETTLED("待结算")
                    info.setStatus(GreenAmountInfoStatusEnum.TO_BE_SETTLED.name());
                    Boolean flag = greenClient.saveSettle(info);
                    if (!flag) {
                        log.info("#executeCityDistributionComissLastMonthOrder# 城主发放收益生成待收益订单失败,城主用户id:{},城主id:{},区域id:{},跳过处理,continue", city.getMemberId(), city.getId(), joinAddress);
                        continue;
                    }
                    //处理城主打款绿色积分
                    UserPointUpdateDTO uDto = new UserPointUpdateDTO();
                    uDto.setUserId(city.getMemberId());
                    uDto.setOrderSn(vo.getOrderSn());
                    uDto.setPoints(vo.getCastellanGreenScore());
                    uDto.setDescription("城主奖励");
                    uDto.setUserPointServiceEnum(UserPointServiceEnum.PAYMENT_GIFT);
                    uDto.setScene(SceneEnums.MEMBER);
                    log.info("#executeCityDistributionComissLastMonthOrder# 处理城主打款绿色积分,UserPointUpdateDTO:{}", JSONObject.toJSONString(uDto));
                    paymentClient.memberCastellan(uDto);
                    ids.add(vo.getOrderFlowId());
                }
                //更新orderFlow表的发放状态
                log.info("#executeCityDistributionComissLastMonthOrder# 更新orderFlow表的发放状态,ids:{}", JSONObject.toJSONString(ids));
                result = orderFlowService.updateCommissStatusInIds(ids);
                //分页查询订单量,继续查询5000条
                pageNum++;
                orderList = orderService.getCityDistributionSumComissByTaskTime(pageNum, pageSize, joinAddress, startDate, endDate);
            }
            log.info("#executeCityDistributionComissLastMonthOrder# 准备进入更新发放收益状态,上个修改订单状态结果为 result:{}", result);
            if (result > 0) {
                //更新城主收益发放状态
                city.setComissStatus(ComissStatusEnum.ALREADLY.type);
                log.info("#executeCityDistributionComissLastMonthOrder# 更新城主收益发放状态,ids:{}", JSONObject.toJSONString(city));
                //这里更改城主发放类型:绿色积分-贡献值
                city.setCommissType(comissType);
                cityDistributionClient.updateCityDistributionById(city);
            }
        }
        //递归直到上个月没有城主
        this.execute(lastMonthDate.minusMonths(1));
        return false;
    }

    @Override
    public Double getCurrentMonthMoneyByMemberId(String memberId) {
        return orderFlowService.getCurrentMonthMoneyByMemberId(memberId);
    }

    @Override
    public Double getLastMonthMoneyByMemberId(String memberId) {
        return orderFlowService.getLastMonthMoneyByMemberId(memberId);
    }

    @Override
    public void executeUnionGreenScoreLastMonthOrder() {
        //上月日期
        LocalDate lastMonthDate = LocalDate.now().minusMonths(2);
        List<Union> unionPage = unionClient.getList();
        //List<OperationCenter> operationCenterList = operationCenterClient.getList();
        //收益类型: 1,贡献值 2,飞语绿色积分
        Integer comissType = null;
        //查询最新功能配置
        GreenConfigValueDTO greenConfigValueDTO = greenClient.getNewGreenConfigValueDTO();
        if(greenConfigValueDTO.getPutinto().getUnion()!=null && greenConfigValueDTO.getPutinto().getUnion()){
            //收益类型为：贡献值
            comissType = 1;
        }else{
            //收益类型:飞语绿色积分
            comissType = 2;
        }
        //查询订单时间条件
        //取上月的第一天为开始日期
        LocalDate startDate = lastMonthDate.withDayOfMonth(1);
        //取下个月1的第一天为结束日期
        LocalDate endDate = startDate.plusMonths(1);
        OperationCenter operation = null;
        String tempOperationProvinceId = "";
        for (Union union : unionPage) {
            //查询运营中心信息
            if (!union.getProvinceId().equals(tempOperationProvinceId)) {
                operation = operationCenterClient.getByAddressId(union.getProvinceId());
                if (operation == null) {
                    continue;
                }
                tempOperationProvinceId = union.getProvinceId();
            }

            int result = 0;
            String joinAddress = union.getCityId();
            //根据区域查询本月的订单
            if (orderService.isExistsUnCompletedOrderByOc(joinAddress, startDate, endDate)) {
                log.info("#executeUnionGreenScoreLastMonthOrder# 上个月还有未完成的订单,工会id:{},区域id:{},跳过处理", union.getId(), joinAddress);
                continue;
            }
            assert operation != null;
            User cityUser = userClient.getById(operation.getUserId());
            if (cityUser == null) {
                log.info("#executeUnionGreenScoreLastMonthOrder# 会长用户信息未找到,会长用户id:{},会长id:{},区域id:{},跳过处理", union.getChairmanId(), union.getId(), joinAddress);
                continue;
            }
            //分页查询订单量,分批执行,1次执行5000条
            int pageNum = 1, pageSize = 5000;
            List<OrderItemViewVO> orderList = orderService.getUnionSumComissByTaskTime(pageNum, pageSize, joinAddress, startDate, endDate);
            while (CollUtil.isNotEmpty(orderList)) {
                List<String> ids = new ArrayList<>();
                for (OrderItemViewVO vo : orderList) {
                    GreenContributionInfo info = new GreenContributionInfo();
                    info.setOrderSn(vo.getOrderSn());
                    //工会会长用户id
//                    info.setUserId(union.getChairmanId());
                    //运营中心用户userid
                    info.setUserId(operation.getUserId());
                    info.setUnionId(union.getId());
                    info.setUserType(SceneEnums.OPERATION_CENTER.name());
                    info.setUsername(cityUser.getUsername());
                    info.setNickName(cityUser.getNickName());
                    info.setFace(cityUser.getFace());
                    info.setScoreNumber(BigDecimal.valueOf(vo.getCastellanGreenScore()));
                    info.setType(GreenAmountInfoTypeEnum.AUTO_DIVIDEND.name());
                    info.setStatus(GreenAmountInfoStatusEnum.TO_BE_SETTLED.name());
                    Boolean flag = greenClient.saveSettle(info);
                    if (!flag) {
                        log.info("#executeUnionGreenScoreLastMonthOrder# 工会发放收益生成待收益订单失败,会长用户id:{},工会id:{},区域id:{},跳过处理,continue", union.getChairmanId(), union.getId(), joinAddress);
                        continue;
                    }
                    //处理会长打款绿色积分
                    UserPointUpdateDTO uDto = new UserPointUpdateDTO();
                    uDto.setUserId(operation.getUserId());
                    uDto.setOrderSn(vo.getOrderSn());
                    uDto.setPoints(vo.getCastellanGreenScore());
                    uDto.setDescription("工会经费");
                    uDto.setUserPointServiceEnum(UserPointServiceEnum.PAYMENT_GIFT);
                    uDto.setScene(SceneEnums.OPERATION_CENTER);
                    paymentClient.memberUnion(uDto);
                    ids.add(vo.getOrderFlowId());
                }
                //更新orderFlow表的发放状态
                result = orderFlowService.updateUnionCommissStatusInIds(ids, comissType);
                //分页查询订单量,继续查询5000条
                pageNum++;
                orderList = orderService.getUnionSumComissByTaskTime(pageNum, pageSize, joinAddress, startDate, endDate);
            }

            if (result > 0) {
                log.info("奖励发放成功：{}", result);
            }
        }
    }

    @Override
    public Page<UnionMonthFundsVO> getUnionCommissByMonth(UnionOrderParams params) {
        return orderFlowService.getUnionCommissByMonth(params);
    }

    @Override
    public boolean updateProfitSharingOrderFlow(String orderSn) {
        LambdaUpdateWrapper<OrderFlow> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(OrderFlow::getOrderSn, orderSn);
        updateWrapper.set(OrderFlow::getProfitSharing, ProfitSharingStatusEnum.FINISHED.name());
        return orderFlowService.update(updateWrapper);
    }

    @Override
    public boolean addOrderFlowProfitSharing(String orderSn, String error) {
        OrderFlowProfitSharingError orderFlowProfitSharingError = new OrderFlowProfitSharingError();
        orderFlowProfitSharingError.setSn(orderSn);
        orderFlowProfitSharingError.setErrorMessage(error);
        return profitSharingErrorService.save(orderFlowProfitSharingError);
    }

    @Override
    public Boolean complete(String orderNo) {
        orderService.complete(orderNo);
        return true;
    }
}
